import math
from appium.webdriver.common.appiumby import AppiumBy
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, StaleElementReferenceException
import logging
import re
from datetime import datetime
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.actions.pointer_input import PointerInput
from selenium.webdriver.common.actions import interaction
from appium.webdriver.extensions.android.nativekey import AndroidKey
from utils.screenshot_util import capture_screenshot

logger = logging.getLogger("AppAutomation")

def find_and_do(driver, action, by, locator, value=None, timeout=30):
    """
    查找元素并执行指定操作
    
    :param driver: WebDriver实例
    :param action: 要执行的操作 ('click', 'send_keys', 'clear')
    :param by: 定位方式 (AppiumBy.ID, AppiumBy.XPATH等)
    :param locator: 定位器字符串
    :param value: 发送的值 (仅在action='send_keys'时需要)
    :param timeout: 超时时间(秒)
    """
    # 等待元素出现
    wait = WebDriverWait(driver, timeout)
    try:
        element = wait.until(EC.presence_of_element_located((by, locator)))
        logger.info(f"元素 '{locator}' 找到并准备执行操作: {action}")
    except TimeoutException:
        logger.error(f"超时等待元素: {locator}")
        # 出现错误时截图
        capture_screenshot(driver, f"timeout_{locator[:30].replace('/', '_').replace(':', '_')}")
        # 不再抛出异常，而是返回False表示失败
        return False

    # 执行指定操作
    try:
        if action == 'click':
            element.click()
        elif action == 'send_keys':
            element.send_keys(value)
        elif action == 'clear':
            element.clear()
        logger.info(f"成功执行操作 '{action}' 在元素: {locator}")
        return True
    except StaleElementReferenceException:
        logger.warning(f"元素 {locator} 已失效，正在重新定位并执行操作.")
        # 元素失效时重新定位
        try:
            element = wait.until(EC.presence_of_element_located((by, locator)))
            if action == 'click':
                element.click()
            elif action == 'send_keys':
                element.send_keys(value)
            elif action == 'clear':
                element.clear()
            logger.info(f"重新定位后成功执行操作 '{action}' 在元素: {locator}")
            return True
        except Exception as e:
            logger.error(f"重新定位后执行操作 '{action}' 在元素 '{locator}' 时发生错误: {str(e)}")
            # 出现错误时截图
            capture_screenshot(driver, f"stale_element_{locator[:30].replace('/', '_').replace(':', '_')}")
            return False
    except Exception as e:
        logger.error(f"执行操作 '{action}' 在元素 '{locator}' 时发生错误: {str(e)}")
        # 出现错误时截图
        capture_screenshot(driver, f"element_error_{locator[:30].replace('/', '_').replace(':', '_')}")
        return False


def perform_touch_action(driver, actions_list):
    """
    执行触摸操作序列
    :param driver: WebDriver实例
    :param actions_list: 包含触摸操作的列表，每个操作是一个字典，包含操作类型和参数
    示例：
    actions_list = [
        {'type': 'move_to', 'x': 493, 'y': 2009},
        {'type': 'pointer_down'},
        {'type': 'pause', 'duration': 0.1},
        {'type': 'pointer_up'}
    ]
    """
    # 创建触摸操作序列
    try:
        actions = ActionChains(driver)
        actions.w3c_actions = ActionBuilder(driver, mouse=PointerInput(interaction.POINTER_TOUCH, "touch"))
        
        # 遍历并执行每个操作
        for action in actions_list:
            if action['type'] == 'move_to':
                actions.w3c_actions.pointer_action.move_to_location(action['x'], action['y'])
            elif action['type'] == 'pointer_down':
                actions.w3c_actions.pointer_action.pointer_down()
            elif action['type'] == 'pointer_up':
                actions.w3c_actions.pointer_action.release()
            elif action['type'] == 'pause':
                actions.w3c_actions.pointer_action.pause(action['duration'])
            elif action['type'] == 'swipe':
                actions.w3c_actions.pointer_action.move_to_location(action['start_x'], action['start_y'])
                actions.w3c_actions.pointer_action.pointer_down()
                actions.w3c_actions.pointer_action.move_to_location(action['end_x'], action['end_y'])
                actions.w3c_actions.pointer_action.release()
            
            # 在每次操作之间添加2秒延迟
            time.sleep(2)
        
        actions.perform()
        logger.info(f"成功执行触摸操作序列: {actions_list}")
    except Exception as e:
        logger.error(f"执行触摸操作序列失败: {str(e)}")
        # 出现错误时截图
        capture_screenshot(driver, "touch_action_error")
        raise

def press_keycode(driver, keycode):
    """
    按下指定的键码
    :param driver: WebDriver实例
    :param keycode: 键码
    """
    try:
        # 尝试使用W3C规范的back方法，如果是返回键(4)
        if keycode == 4:
            driver.back()
            logger.info(f"成功执行返回操作")
        else:
            # 对于其他键码，尝试使用mobile命令
            driver.execute_script('mobile: pressKey', {"keycode": keycode})
            logger.info(f"成功按下键码: {keycode}")
    except Exception as e:
        logger.error(f"按下键码 {keycode} 失败: {str(e)}")
        # 出现错误时截图
        capture_screenshot(driver, f"press_keycode_error_{keycode}")
        # 如果mobile: pressKey失败，尝试使用press_keycode方法（适用于Android）
        try:
            driver.press_keycode(keycode)
            logger.info(f"通过press_keycode成功按下键码: {keycode}")
        except Exception as fallback_error:
            logger.error(f"通过fallback方法按下键码 {keycode} 也失败了: {str(fallback_error)}")
            # 出现错误时截图
            capture_screenshot(driver, f"fallback_press_keycode_error_{keycode}")
            raise

def switch_to_context(driver, context_name):
    """
    切换到指定的上下文
    :param driver: WebDriver实例
    :param context_name: 上下文名称
    """
    try:
        driver.switch_to.context(context_name)
        logger.info(f"成功切换到上下文: {context_name}")
    except Exception as e:
        logger.error(f"切换到上下文 {context_name} 失败: {str(e)}")
        # 出现错误时截图
        capture_screenshot(driver, f"context_switch_error_{context_name}")
        raise

def perform_swipe_sequence(driver, swipes):
    """
    执行一系列滑动操作
    :param driver: Appium WebDriver 实例
    :param swipes: 滑动操作列表，每个元素应包含start_x, start_y, end_x, end_y, duration参数
    """
    try:
        # 遍历并执行每个滑动操作
        for i, swipe in enumerate(swipes):
            start_x = swipe.get('start_x')
            start_y = swipe.get('start_y')
            end_x = swipe.get('end_x')
            end_y = swipe.get('end_y')
            duration = swipe.get('duration', 1000)
            
            driver.swipe(start_x, start_y, end_x, end_y, duration)
            logger.info(f"执行第 {i+1} 个滑动操作: 从 ({start_x}, {start_y}) 到 ({end_x}, {end_y})")
            time.sleep(5)  # 每次滑动之间暂停5秒
    except Exception as e:
        logger.error(f"执行滑动序列失败: {str(e)}")
        # 出现错误时截图
        capture_screenshot(driver, "swipe_sequence_error")
        raise